package com.wuhunyu.filter;

import com.wuhunyu.commonutils.check.Check;
import com.wuhunyu.security.TokenManager;
import com.wuhunyu.servicebase.exception.Assert;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 授权过滤器
 * @author wuhunyu
 */
public class TokenAuthenticationFilter extends BasicAuthenticationFilter {

    private TokenManager tokenManager;

    private RedisTemplate redisTemplate;

    public TokenAuthenticationFilter(AuthenticationManager authManager, TokenManager tokenManager,RedisTemplate redisTemplate) {
        super(authManager);
        this.tokenManager = tokenManager;
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) {
        // 若url中包含了acl，则放行
        if(req.getRequestURI().indexOf("acl") == -1) {
            try {
                chain.doFilter(req, res);
            } catch (Exception e) {
                Assert.isRight(true, "权限放行失败");
            }
            return ;
        }
        UsernamePasswordAuthenticationToken authentication = null;
        try {
            authentication = getAuthentication(req);
        } catch (Exception e) {
            Assert.isRight(true, "解析token字符串异常");
        }
        // 将权限放入权限上下文中
        if (Check.isNotBlank(authentication)) {
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } else {
            Assert.isRight(true, "错误");
        }
        try {
            chain.doFilter(req, res);
        } catch (Exception e) {
            Assert.isRight(true, "权限放行失败");
        }
    }

    /**
     * 解析token字符串，并返回授权对象
     * @param request
     * @return
     */
    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        // 获取header中的token
        String token = request.getHeader("wuhunyu_token");
        if (Check.isNotBlank(token)) {
            // 解析token中的用户名
            String userName = tokenManager.getUserFromToken(token);
            // 如果userName为空
            if (Check.isBlank(userName)) {
                return null;
            }
            // 获取redis中存储的权限列表,并封装到list集合中
            List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(userName);
            Collection<GrantedAuthority> authorities = new ArrayList<>();
            for (String permissionValue : permissionValueList) {
                if (Check.isNotBlank(permissionValue)) {
                    SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
                    authorities.add(authority);
                }
            }
            // 返回授权对象
            return new UsernamePasswordAuthenticationToken(userName, token, authorities);
        }
        // 解析token字符串失败
        Assert.isRight(true, "解析token字符串失败");
        return null;
    }
}